using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using Volo.Abp.ObjectMapping;
using Matrix.Configuration.DTOs;

namespace Matrix.Configuration.Configuration
{
    /// <summary>
    /// 配置缓存预热服务
    /// 用于预加载热点配置到缓存中
    /// </summary>
    public class WarmupCacheJobArgs
    {
        public int MaxCount { get; set; } = 100;
    }

    /// <summary>
    /// 命名空间缓存预热作业参数
    /// </summary>
    public class WarmupNamespaceCacheJobArgs
    {
        public string Namespace { get; set; } = string.Empty;
        public int MaxCount { get; set; } = 50;
    }

    /// <summary>
    /// 刷新配置缓存作业参数
    /// </summary>
    public class RefreshConfigurationCacheJobArgs
    {
        public Guid TenantId { get; set; }
        public string Namespace { get; set; } = string.Empty;
        public string Name { get; set; } = string.Empty;
    }

    /// <summary>
    /// 清空所有缓存作业参数
    /// </summary>
    public class ClearAllCacheJobArgs
    {
    }

    /// <summary>
    /// 清空租户缓存作业参数
    /// </summary>
    public class ClearTenantCacheJobArgs
    {
        public Guid TenantId { get; set; }
    }

    /// <summary>
    /// 缓存预热后台作业
    /// </summary>
    public class WarmupCacheJob : AsyncBackgroundJob<WarmupCacheJobArgs>, ITransientDependency
    {
        private readonly ConfigurationCacheWarmer _cacheWarmer;
        private readonly ILogger<WarmupCacheJob> _logger;

        public WarmupCacheJob(
            ConfigurationCacheWarmer cacheWarmer,
            ILogger<WarmupCacheJob> logger)
        {
            _cacheWarmer = cacheWarmer;
            _logger = logger;
        }

        public override async Task ExecuteAsync(WarmupCacheJobArgs args)
        {
            _logger.LogInformation("执行缓存预热后台作业，最大数量: {MaxCount}", args.MaxCount);
            await _cacheWarmer.WarmupCacheAsync(args.MaxCount);
        }
    }

    /// <summary>
    /// 命名空间缓存预热后台作业
    /// </summary>
    public class WarmupNamespaceCacheJob : AsyncBackgroundJob<WarmupNamespaceCacheJobArgs>, ITransientDependency
    {
        private readonly ConfigurationCacheWarmer _cacheWarmer;
        private readonly ILogger<WarmupNamespaceCacheJob> _logger;

        public WarmupNamespaceCacheJob(
            ConfigurationCacheWarmer cacheWarmer,
            ILogger<WarmupNamespaceCacheJob> logger)
        {
            _cacheWarmer = cacheWarmer;
            _logger = logger;
        }

        public override async Task ExecuteAsync(WarmupNamespaceCacheJobArgs args)
        {
            _logger.LogInformation("执行命名空间缓存预热后台作业: {Namespace}, 最大数量: {MaxCount}",
                args.Namespace, args.MaxCount);
            await _cacheWarmer.WarmupNamespaceCacheAsync(args.Namespace, args.MaxCount);
        }
    }

    /// <summary>
    /// 刷新配置缓存后台作业
    /// </summary>
    public class RefreshConfigurationCacheJob : AsyncBackgroundJob<RefreshConfigurationCacheJobArgs>, ITransientDependency
    {
        private readonly ConfigurationCacheWarmer _cacheWarmer;
        private readonly ILogger<RefreshConfigurationCacheJob> _logger;

        public RefreshConfigurationCacheJob(
            ConfigurationCacheWarmer cacheWarmer,
            ILogger<RefreshConfigurationCacheJob> logger)
        {
            _cacheWarmer = cacheWarmer;
            _logger = logger;
        }

        public override async Task ExecuteAsync(RefreshConfigurationCacheJobArgs args)
        {
            _logger.LogInformation("执行刷新配置缓存后台作业: {TenantId}, {Namespace}, {Name}",
                args.TenantId, args.Namespace, args.Name);
            await _cacheWarmer.RefreshConfigurationCacheAsync(args.TenantId, args.Namespace, args.Name);
        }
    }

    /// <summary>
    /// 清空所有缓存后台作业
    /// </summary>
    public class ClearAllCacheJob : AsyncBackgroundJob<ClearAllCacheJobArgs>, ITransientDependency
    {
        private readonly ConfigurationCacheWarmer _cacheWarmer;
        private readonly ILogger<ClearAllCacheJob> _logger;

        public ClearAllCacheJob(
            ConfigurationCacheWarmer cacheWarmer,
            ILogger<ClearAllCacheJob> logger)
        {
            _cacheWarmer = cacheWarmer;
            _logger = logger;
        }

        public override async Task ExecuteAsync(ClearAllCacheJobArgs args)
        {
            _logger.LogInformation("执行清空所有缓存后台作业");
            await _cacheWarmer.ClearAllCacheAsync();
        }
    }

    /// <summary>
    /// 清空租户缓存后台作业
    /// </summary>
    public class ClearTenantCacheJob : AsyncBackgroundJob<ClearTenantCacheJobArgs>, ITransientDependency
    {
        private readonly ConfigurationCacheWarmer _cacheWarmer;
        private readonly ILogger<ClearTenantCacheJob> _logger;

        public ClearTenantCacheJob(
            ConfigurationCacheWarmer cacheWarmer,
            ILogger<ClearTenantCacheJob> logger)
        {
            _cacheWarmer = cacheWarmer;
            _logger = logger;
        }

        public override async Task ExecuteAsync(ClearTenantCacheJobArgs args)
        {
            _logger.LogInformation("执行清空租户缓存后台作业: {TenantId}", args.TenantId);
            await _cacheWarmer.ClearTenantCacheAsync(args.TenantId);
        }
    }

    public class ConfigurationCacheWarmer : ITransientDependency
    {
        private readonly IRepository<ConfigurationItem, Guid> _repository;
        private readonly SmartConfigurationCacheManager _cacheManager;
        private readonly ILogger<ConfigurationCacheWarmer> _logger;
        private readonly IObjectMapper _objectMapper;
        private readonly IAsyncQueryableExecuter _asyncExecuter;

        public ConfigurationCacheWarmer(
            IRepository<ConfigurationItem, Guid> repository,
            SmartConfigurationCacheManager cacheManager,
            ILogger<ConfigurationCacheWarmer> logger,
            IObjectMapper objectMapper,
            IAsyncQueryableExecuter asyncExecuter)
        {
            _repository = repository;
            _cacheManager = cacheManager;
            _logger = logger;
            _objectMapper = objectMapper;
            _asyncExecuter = asyncExecuter;
        }

        /// <summary>
        /// 预热缓存
        /// </summary>
        /// <param name="maxCount">预热的最大配置项数量，默认100</param>
        public async Task WarmupCacheAsync(int maxCount = 100)
        {
            _logger.LogInformation("开始缓存预热，最大数量: {MaxCount}", maxCount);

            try
            {
                var warmupCount = await WarmupHotConfigurationsAsync(maxCount);
                _logger.LogInformation("缓存预热完成，实际预热数量: {Count}", warmupCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "缓存预热过程中发生错误");
                throw;
            }
        }

        /// <summary>
        /// 预热指定命名空间的配置
        /// </summary>
        /// <param name="namespace">命名空间</param>
        /// <param name="maxCount">最大数量</param>
        // Background job - managed by IBackgroundJobManager
        public async Task WarmupNamespaceCacheAsync(string @namespace, int maxCount = 50)
        {
            if (string.IsNullOrWhiteSpace(@namespace))
            {
                _logger.LogWarning("命名空间为空，跳过预热");
                return;
            }

            _logger.LogInformation("开始预热命名空间缓存: {Namespace}, 最大数量: {MaxCount}", @namespace, maxCount);

            try
            {
                var warmupCount = await WarmupNamespaceConfigurationsAsync(@namespace, maxCount);
                _logger.LogInformation("命名空间缓存预热完成: {Namespace}, 数量: {Count}", @namespace, warmupCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "预热命名空间缓存时发生错误: {Namespace}", @namespace);
            }
        }

        /// <summary>
        /// 刷新指定配置的缓存
        /// </summary>
        /// <param name="tenantId">租户ID</param>
        /// <param name="namespace">命名空间</param>
        /// <param name="name">配置名称</param>
        // Background job - managed by IBackgroundJobManager
        public async Task RefreshConfigurationCacheAsync(Guid? tenantId, string @namespace, string name)
        {
            var cacheKey = GetCacheKey(tenantId, @namespace, name);

            try
            {
                // 从数据库获取最新配置
                var queryable = await _repository.GetQueryableAsync();
                var configuration = await _asyncExecuter.FirstOrDefaultAsync(
                    queryable.Where(x =>
                        x.TenantId == tenantId &&
                        x.Namespace == @namespace &&
                        x.Key == name));

                if (configuration != null)
                {
                    var dto = _objectMapper.Map<ConfigurationItem, ConfigurationItemDto>(configuration);
                    await _cacheManager.SetAsync(cacheKey, dto);
                    _logger.LogDebug("配置缓存刷新成功: {CacheKey}", cacheKey);
                }
                else
                {
                    // 配置不存在，删除缓存
                    await _cacheManager.RemoveAsync(cacheKey);
                    _logger.LogDebug("配置不存在，已删除缓存: {CacheKey}", cacheKey);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "刷新配置缓存时发生错误: {CacheKey}", cacheKey);
            }
        }

        /// <summary>
        /// 清空所有缓存
        /// </summary>
        // Background job - managed by IBackgroundJobManager
        public async Task ClearAllCacheAsync()
        {
            _logger.LogInformation("开始清空所有配置缓存");

            try
            {
                await _cacheManager.ClearAsync();
                _logger.LogInformation("所有配置缓存清空完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清空缓存时发生错误");
                throw;
            }
        }

        /// <summary>
        /// 清空指定租户的缓存
        /// </summary>
        /// <param name="tenantId">租户ID</param>
        // Background job - managed by IBackgroundJobManager
        public async Task ClearTenantCacheAsync(Guid tenantId)
        {
            _logger.LogInformation("开始清空租户缓存: {TenantId}", tenantId);

            try
            {
                // 获取该租户的所有配置键
                var queryable = await _repository.GetQueryableAsync();
                var configurations = await _asyncExecuter.ToListAsync(
                    queryable.Where(x => x.TenantId == tenantId).Take(1000)); // 限制数量避免内存问题

                var keys = configurations.Select(x => GetCacheKey(x.TenantId, x.Namespace, x.Key)).ToList();

                if (keys.Any())
                {
                    await _cacheManager.RemoveBatchAsync(keys);
                    _logger.LogInformation("租户缓存清空完成: {TenantId}, 数量: {Count}", tenantId, keys.Count);
                }
                else
                {
                    _logger.LogInformation("租户没有配置项需要清空: {TenantId}", tenantId);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清空租户缓存时发生错误: {TenantId}", tenantId);
            }
        }

        /// <summary>
        /// 预热热点配置
        /// </summary>
        private async Task<int> WarmupHotConfigurationsAsync(int maxCount)
        {
            var queryable = await _repository.GetQueryableAsync();

            // 按最后修改时间排序，预加载最近使用的配置
            var hotConfigs = await _asyncExecuter.ToListAsync(
                queryable
                    .OrderByDescending(x => x.LastModificationTime ?? x.CreationTime)
                    .Take(maxCount));

            if (!hotConfigs.Any())
            {
                _logger.LogWarning("没有找到需要预热的配置项");
                return 0;
            }

            // 分批预热，避免单次操作过多
            const int batchSize = 10;
            var batches = hotConfigs.Chunk(batchSize);

            var totalWarmed = 0;
            foreach (var batch in batches)
            {
                var tasks = batch.Select(async config =>
                {
                    try
                    {
                        var cacheKey = GetCacheKey(config.TenantId, config.Namespace, config.Key);
                        var dto = _objectMapper.Map<ConfigurationItem, ConfigurationItemDto>(config);
                        await _cacheManager.SetAsync(cacheKey, dto);
                        return true;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "预热配置项失败: {Namespace}/{Key}", config.Namespace, config.Key);
                        return false;
                    }
                });

                var results = await Task.WhenAll(tasks);
                totalWarmed += results.Count(r => r);
            }

            return totalWarmed;
        }

        /// <summary>
        /// 预热指定命名空间的配置
        /// </summary>
        private async Task<int> WarmupNamespaceConfigurationsAsync(string @namespace, int maxCount)
        {
            var queryable = await _repository.GetQueryableAsync();

            var namespaceConfigs = await _asyncExecuter.ToListAsync(
                queryable
                    .Where(x => x.Namespace == @namespace)
                    .OrderByDescending(x => x.LastModificationTime ?? x.CreationTime)
                    .Take(maxCount));

            if (!namespaceConfigs.Any())
            {
                _logger.LogWarning("命名空间 {Namespace} 没有找到配置项", @namespace);
                return 0;
            }

            // 分批预热
            const int batchSize = 10;
            var batches = namespaceConfigs.Chunk(batchSize);

            var totalWarmed = 0;
            foreach (var batch in batches)
            {
                var tasks = batch.Select(async config =>
                {
                    try
                    {
                        var cacheKey = GetCacheKey(config.TenantId, config.Namespace, config.Key);
                        var dto = _objectMapper.Map<ConfigurationItem, ConfigurationItemDto>(config);
                        await _cacheManager.SetAsync(cacheKey, dto);
                        return true;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "预热命名空间配置项失败: {Namespace}/{Key}", config.Namespace, config.Key);
                        return false;
                    }
                });

                var results = await Task.WhenAll(tasks);
                totalWarmed += results.Count(r => r);
            }

            return totalWarmed;
        }

        /// <summary>
        /// 获取缓存键
        /// </summary>
        private string GetCacheKey(Guid? tenantId, string @namespace, string name)
        {
            // 格式: config:{tenantId}:{namespace}:{name}
            return $"config:{tenantId?.ToString() ?? "global"}:{@namespace}:{name}";
        }

        /// <summary>
        /// 获取缓存键（从配置项）
        /// </summary>
        private string GetCacheKey(ConfigurationItem config)
        {
            return GetCacheKey(config.TenantId, config.Namespace, config.Key);
        }

        /// <summary>
        /// 获取配置使用统计
        /// </summary>
        // Background job - managed by IBackgroundJobManager
        public async Task<ConfigurationUsageStatistics> GetUsageStatisticsAsync()
        {
            var queryable = await _repository.GetQueryableAsync();

            var totalCount = await _asyncExecuter.CountAsync(queryable);
            var tenantCount = await _asyncExecuter.CountAsync(queryable.Where(x => x.TenantId != null));
            var globalCount = totalCount - tenantCount;

            // 按命名空间分组统计
            var namespaceStats = await _asyncExecuter.ToListAsync(
                queryable
                    .GroupBy(x => x.Namespace)
                    .Select(g => new
                    {
                        Namespace = g.Key,
                        Count = g.Count(),
                        LastModified = g.Max(x => x.LastModificationTime ?? x.CreationTime)
                    })
                    .OrderByDescending(x => x.Count));

            var stats = new ConfigurationUsageStatistics
            {
                TotalConfigurations = totalCount,
                TenantConfigurations = tenantCount,
                GlobalConfigurations = globalCount,
                NamespaceStatistics = namespaceStats.Select(x => new NamespaceStatistics
                {
                    Namespace = x.Namespace,
                    Count = x.Count,
                    LastModified = x.LastModified
                }).ToList()
            };

            return stats;
        }
    }

    /// <summary>
    /// 配置使用统计信息
    /// </summary>
    public class ConfigurationUsageStatistics
    {
        /// <summary>
        /// 总配置数
        /// </summary>
        public int TotalConfigurations { get; set; }

        /// <summary>
        /// 租户配置数
        /// </summary>
        public int TenantConfigurations { get; set; }

        /// <summary>
        /// 全局配置数
        /// </summary>
        public int GlobalConfigurations { get; set; }

        /// <summary>
        /// 命名空间统计
        /// </summary>
        public List<NamespaceStatistics> NamespaceStatistics { get; set; } = new();
    }

    /// <summary>
    /// 命名空间统计信息
    /// </summary>
    public class NamespaceStatistics
    {
        /// <summary>
        /// 命名空间名称
        /// </summary>
        public string Namespace { get; set; } = string.Empty;

        /// <summary>
        /// 配置数量
        /// </summary>
        public int Count { get; set; }

        /// <summary>
        /// 最后修改时间
        /// </summary>
        public DateTime? LastModified { get; set; }
    }
}